package org.jeecg.common.util.rest;

import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Map;

/***
 * HTTP 请求封装类
 * @author wmf
 * Create at 2019-12-12 11:37
 */
public class RestTemplateUtil {

    private static final Boolean ignoreSSL = true;

    /**
     * 不带参的get请求
     */
    public static Notice restTemplateGet(String url){
        RestTemplate restTemplate = new RestTemplate();
        Notice notice = restTemplate.getForObject(url , Notice.class);
        return notice;
    }

    /**
     * 带参数的PathVariable get请求
     * Map<String,String> map = new HashMap();
     *         map.put("start","1");
     *         map.put("page","5");
     */
    public static Notice restTemplateGetByPathVariable(String url,Object ...obj){
        RestTemplate restTemplate = new RestTemplate();
        Notice notice = restTemplate.getForObject(url , Notice.class, obj);
        return notice;
    }

    /**
     * 带参数的Map get请求
     * Notice notice = restTemplate.getForObject("http://fantj.top/notice/list/{1}/{2}"
     *                 , Notice.class,1,5);
     */
    public static Notice restTemplateGetMap(String url, Map<String,Object> map){
        RestTemplate restTemplate = new RestTemplate();
        Notice notice = restTemplate.getForObject(url , Notice.class, map);
        return notice;
    }

    public void rtGetEntity(){
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<Notice> entity = restTemplate.getForEntity("http://fantj.top/notice/list/1/5"
                , Notice.class);

        HttpStatus statusCode = entity.getStatusCode();
        System.out.println("statusCode.is2xxSuccessful()"+statusCode.is2xxSuccessful());

        Notice body = entity.getBody();
        System.out.println("entity.getBody()"+body);


        ResponseEntity.BodyBuilder status = ResponseEntity.status(statusCode);
        status.contentLength(100);
        status.body("我在这里添加一句话");
        ResponseEntity<Class<Notice>> body1 = status.body(Notice.class);
        Class<Notice> body2 = body1.getBody();
        System.out.println("body1.toString()"+body1.toString());
    }

    /**
     * Get 请求
     * @param url 请求地址
     * @param headers 请求头
     * @return
     */
    public static String rtGetObject(String url, HttpHeaders headers){
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.exchange(
                url,
                HttpMethod.GET,
                new HttpEntity<String>(headers),
                String.class);
        return response.getBody();
    }



    /**
     * POST 请求
     * @param url 请求地址
     * @param map  map.add("email", "844072586@qq.com");
     * @return
     */
    public static String rtPostObject(String url, MultiValueMap<String, String> map){
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
        ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );
        return response.getBody();
    }

    /**
     * POST 请求
     * @param url 请求地址
     * @param headers 请求头
     * @param map  map.add("email", "844072586@qq.com");
     * @return
     */
    public static String rtPostObject(String url, HttpHeaders headers, MultiValueMap<String, String> map){
        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
        ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );
        return response.getBody();
    }


    /**
     *
     * @param url 请求地址
     * @param jsonObj JSON对象
     * @param httpMethod HttpMethod.GET,HttpMethod.POST
     * @return
     * @throws JSONException
     */
    public static JSONObject rtExchangeTest(String url, JSONObject jsonObj, HttpMethod httpMethod) throws JSONException {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<String> entity = new HttpEntity<>(jsonObj.toString(), headers);
        ResponseEntity<JSONObject> exchange = restTemplate.exchange(url,
                httpMethod, entity, JSONObject.class);

        return exchange.getBody();
    }

/* ============= 分割线以下是https请求 ================= */


    /**
     * 绕过SSL验证
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sslContext = SSLContext.getInstance("SSLv3");

        // 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(
                    X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(
                    X509Certificate[] paramArrayOfX509Certificate,
                    String paramString) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        sslContext.init(null, new TrustManager[] { trustManager }, null);
        return sslContext;
    }


    /**
     * 绕过SSL证书，发送Get请求
     * @param url
     * @param params
     * @return
     * @throws IOException
     * @throws KeyManagementException
     * @throws NoSuchAlgorithmException
     */
    public static String doIgnoreVerifySSLGet(String url, Map<String,Object> params)
            throws IOException, KeyManagementException, NoSuchAlgorithmException {
        //采用绕过验证的方式处理https请求
        SSLContext sslContext = createIgnoreVerifySSL();
        final SSLConnectionSocketFactory sslsf;

        //设置协议http和https对应的处理socket链接工厂的对象
        sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", sslsf)
                .build();

        final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
        cm.setMaxTotal(100);

        //创建自定义的httpclient对象
        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .setConnectionManager(cm)
                .build();

        String result = null;
        //装填参数
        StringBuffer param = new StringBuffer();
        if (params != null && !params.isEmpty()) {
            int i = 0;
            for (String key : params.keySet()) {
                if (i == 0) {
                    param.append("?");
                } else {
                    param.append("&");
                }
                param.append(key).append("=").append(params.get(key));
                i++;
            }
            url += param;
        }
        //创建get方式请求对象
        HttpGet httpGet = new HttpGet(url);
        //执行请求操作，并拿到结果（同步阻塞）
        CloseableHttpResponse response = httpClient.execute(httpGet);
        if (response.getStatusLine().getStatusCode() == 200){
            //获取结果实体
            org.apache.http.HttpEntity httpEntity = response.getEntity();
            //按指定编码转换结果实体为String类型
            result = EntityUtils.toString(httpEntity,"UTF-8");
        }

        //释放链接
        response.close();

        return result;
    }

    /**
     * 绕过SSL证书，发送Post请求（Json形式）
     * @param url
     * @param param
     * @return
     * @throws IOException
     * @throws KeyManagementException
     * @throws NoSuchAlgorithmException
     */
    public static String doIgnoreVerifySSLPost(String url, JSONObject param)
            throws IOException, KeyManagementException, NoSuchAlgorithmException {
        //采用绕过验证的方式处理https请求
        SSLContext sslContext = createIgnoreVerifySSL();
        final SSLConnectionSocketFactory sslsf;

        //设置协议http和https对应的处理socket链接工厂的对象
        sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
        final Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", sslsf)
                .build();

        final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
        cm.setMaxTotal(100);

        //创建自定义的httpclient对象
        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .setConnectionManager(cm)
                .build();

        String result = null;
        //创建post方式请求对象
        HttpPost httpPost = new HttpPost(url);
        //装填参数
        StringEntity entity = new StringEntity(param.toString(),"utf-8");
        entity.setContentEncoding("UTF-8");
        entity.setContentType("application/json");
        //设置参数到请求对象中
        httpPost.setEntity(entity);

        //执行请求操作，并拿到结果（同步阻塞）
        CloseableHttpResponse response = httpClient.execute(httpPost);
        if (response.getStatusLine().getStatusCode() == 200){
            //获取结果实体
            org.apache.http.HttpEntity httpEntity = response.getEntity();
            //按指定编码转换结果实体为String类型
            result = EntityUtils.toString(httpEntity,"UTF-8");
        }

        //释放链接
        response.close();

        return result;
    }



    /**
     * POST 请求 Requestbody (JSON格式)
     * @param url 请求地址
     * @param json  json.put("authType", "2");
     * @return
     */
    public static String rtHttpsPostObject(String url, JSONObject json){
        RestTemplate restTemplate = buildRestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        HttpEntity request = new HttpEntity<>(json.toJSONString(), headers);
        String s = restTemplate.postForObject(url,request,String.class);
    //    ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );
     //   return response.getBody();
        return s;
    }

    /**
     *  初始化HTTPs 的 restTemplate
     * @return
     */
    public static RestTemplate buildRestTemplate() {

        RestTemplate restTemplate = new RestTemplate();
        if (ignoreSSL) {//ignoreSSL为true时，绕过证书
            HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
            factory.setConnectionRequestTimeout(300000);
            factory.setConnectTimeout(300000);
            factory.setReadTimeout(300000);
            // https
            CloseableHttpClient httpClient = getHttpsClient();
            factory.setHttpClient(httpClient);
            restTemplate = new RestTemplate(factory);
        }
 //       reInitMessageConverter(restTemplate);
        return restTemplate;
    }

    /**
     *  初始化HTTPs 的 httpClient
     * @return
     */
    public static CloseableHttpClient getHttpsClient() {

        CloseableHttpClient httpClient;
        if (ignoreSSL) {//ignoreSSL为true时，绕过证书
            SSLContext sslContext = null;
            try {
                sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
                        return true;
                    }
                }).build();
            } catch (NoSuchAlgorithmException e) {
                e.getStackTrace();
            } catch (KeyManagementException e) {
                e.getStackTrace();
            } catch (KeyStoreException e) {
                e.getStackTrace();
            }
            httpClient = HttpClients.custom().setSSLContext(sslContext).
                    setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
        } else {
            httpClient = HttpClients.createDefault();
        }
        return httpClient;
    }

}
